package com.ruoyi.system.service.impl;

import com.ruoyi.system.service.ArticleLuceneService;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@Service
public class ArticleLuceneServiceImpl implements ArticleLuceneService {
    private Directory directory = null;
    private IndexReader indexReader = null;
    @Value("${lucene.indexPath}")
    private String indexPath;
    private IndexWriterConfig config;
    private Analyzer analyzer;
    @PostConstruct
    public void pre(){
        try {
            analyzer = new IKAnalyzer();
            config = new IndexWriterConfig(analyzer);
            directory = FSDirectory.open(Paths.get(indexPath));
            indexReader = DirectoryReader.open(directory);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void createIndex(String id, String content) throws IOException {
        IndexWriter indexWriter = new IndexWriter(directory, config);

        Document doc = new Document();
        doc.add(new StringField("id", id, Field.Store.YES));
        doc.add(new TextField("content", content, Field.Store.YES));

        indexWriter.addDocument(doc);
        indexWriter.commit();
        indexWriter.close();
    }

    @Override
    public void deleteIndex(String id) throws IOException {
        IndexWriter indexWriter = new IndexWriter(directory, config);

        indexWriter.deleteDocuments(new Term("id", id));
        indexWriter.commit();
        indexWriter.close();
    }

    @Override
    public void updateIndex(String id, String content) throws IOException {
        IndexWriter indexWriter = new IndexWriter(directory, config);

        Document doc = new Document();
        doc.add(new StringField("id", id, Field.Store.YES));
        doc.add(new TextField("content", content, Field.Store.YES));

        indexWriter.updateDocument(new Term("id", id), doc);
        indexWriter.commit();
        indexWriter.close();
    }

    @Override
    public List<String> searchIndexWithPagination(String queryString, int pageNumber, int pageSize) throws IOException, ParseException {
        if (pageNumber < 1 || pageSize < 1) {
            throw new IllegalArgumentException("pageNumber and pageSize must be greater than 0.");
        }
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        QueryParser queryParser = new QueryParser("content", analyzer);
        Query query = queryParser.parse(queryString);

        int startIndex = (pageNumber - 1) * pageSize;
        ScoreDoc lastScoreDoc = null;

        if (startIndex > 0) {
            TopDocs previousTopDocs = indexSearcher.search(query, startIndex);
            lastScoreDoc = previousTopDocs.scoreDocs[startIndex - 1];
        }

        TopDocs topDocs = indexSearcher.searchAfter(lastScoreDoc, query, pageSize);

        List<String> searchResults = new ArrayList<>();
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = indexSearcher.doc(scoreDoc.doc);
            searchResults.add("id: " + doc.get("id") + ", content: " + doc.get("content"));
        }

        indexReader.close();
        return searchResults;
    }
}
